package cn.o.generate.aspect;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.Response;
import java.util.Arrays;

/**
 * @Description
 * @auther Teler
 * @create 2019-08-30 10:19
 */
@Component
@Aspect
public class AopHandlerAspect {
    private Log logger = LogFactory.get();

    ThreadLocal<Long> startTime = new ThreadLocal<>();


    @Pointcut("execution(public * cn.o.generate.controller.*.*(..))")
    public void pointCut() {}

    @Before("pointCut()")
    public void before(JoinPoint joinPoint) throws Throwable {
        logger.info("==================前置执行=====================>");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        logger.info("请求来源： =》" + request.getRemoteAddr());
        logger.info("请求URL：" + request.getRequestURL().toString());
        logger.info("请求方式：" + request.getMethod());
        logger.info("响应方法：" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("请求参数：" + Arrays.toString(joinPoint.getArgs()));
        logger.info("==================前置执行完成==================>");
        startTime.set(System.currentTimeMillis());
    }

    // 定义需要匹配的切点表达式，同时需要匹配参数
    @Around("pointCut() && args(arg)")
    public Response around(ProceedingJoinPoint pjp, String arg) throws Throwable {
        logger.info("name:" + arg);
        logger.info("方法环绕start...around");
        String result = null;
        try {
            result = pjp.proceed().toString() + "aop String";
            logger.info(result);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        logger.info("方法环绕end...around");
        return (Response) pjp.proceed();
    }


    @After("pointCut()")
    public void after(JoinPoint point) {
        if (startTime.get() == null) {
            startTime.set(System.currentTimeMillis());
        }
        logger.info("==================后置执行======================>");
        logger.info("耗时（毫秒）：" + (System.currentTimeMillis() - startTime.get()));
        logger.info("返回数据：{}", point.getArgs());
        logger.info("==================后置执行完成==================>");
    }
}
